package com.eye.system.util;

import com.eye.system.exception.DMPException;
import org.springframework.cglib.beans.BeanMap;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class CommonUtil {
    /**
     * 毫秒时间格式
     */
    public static final String FORMAT_STR_MILLISECOND = "yyyy-MM-dd HH:mm:ss SS";
    public static final String FORMAT_STR_SECOND = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_STR_DAY = "yyyy-MM-dd";

    public static final char UNDERLINE = '_';

    /**
     * 下载文件
     *
     * @param response  响应
     * @param fileInput 下载文件输入流
     * @param fileName  下载文件名称
     */
    public static void downloadFile(HttpServletResponse response, InputStream fileInput, String fileName) {
        try {
            //配置
            response.setHeader("Content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try (OutputStream os = response.getOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fileInput.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInput != null) {
                try {
                    fileInput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 字符串转LocalDateTime
     *
     * @param string    时间字符串
     * @param formatStr 时间格式
     * @return LocalDateTime
     */
    public static LocalDateTime stringToLocalDateTime(String string, String formatStr) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(formatStr);
        if (!string.contains(":")) {
            return LocalDate.parse(string, df).atStartOfDay();
        }
        return LocalDateTime.parse(string, df);
    }

    /**
     * LocalDateTime转字符串
     *
     * @param localDateTime LocalDateTime
     * @param formatStr     时间格式
     * @return 字符串
     */
    public static String localDateTimeToString(LocalDateTime localDateTime, String formatStr) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(formatStr);
        return df.format(localDateTime);
    }

    /**
     * LocalDateTime转时间戳
     *
     * @param localDateTime LocalDateTime
     * @param timezone      时区(默认:+8)
     * @return 时间戳(毫秒)
     */
    public static Long localDateTimeToTimestamp(LocalDateTime localDateTime, String timezone) {
        if (timezone == null || "".equals(timezone)) {
            timezone = "+8";
        }
        return localDateTime.toInstant(ZoneOffset.of(timezone)).toEpochMilli();
    }

    /**
     * 时间戳转LocalDateTime
     *
     * @param timestamp 时间戳
     * @param timezone  时区(默认:+8)
     * @return LocalDateTime
     */
    public static LocalDateTime timestampToLocalDateTime(Long timestamp, String timezone) {
        if (timezone == null || "".equals(timezone)) {
            timezone = "+8";
        }
        return new Date(timestamp)
                .toInstant()
                .atOffset(ZoneOffset.of(timezone))
                .toLocalDateTime();
    }

    /**
     * 获取系统当前时间
     *
     * @param formatStr 时间格式
     * @return 系统当前时间字符串
     */
    public static String getSystemTime(String formatStr) {
        if (formatStr == null || "".equals(formatStr)) {
            formatStr = FORMAT_STR_MILLISECOND;
        }
        return new SimpleDateFormat(formatStr).format(Calendar.getInstance().getTime());
    }

    /**
     * 给定字符串是否匹配给定正则
     *
     * @param regex   给定正则
     * @param content 给定字符串
     * @return -
     */
    public static boolean isMatch(String regex, CharSequence content) {
        if (content == null) {
            return false;
        } else if (regex == null || "".equals(regex)) {
            return true;
        } else {
            Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
            return pattern.matcher(content).matches();
        }
    }

    /**
     * 驼峰格式字符串转换为下划线格式字符串
     *
     * @param param
     * @return
     */
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        StringBuilder sb = new StringBuilder(param.length());
        param.chars().forEach(ele -> {
            if (Character.isUpperCase(ele)) {
                sb.append(UNDERLINE);
                sb.append((char) Character.toLowerCase(ele));
            } else {
                sb.append((char) ele);
            }
        });
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * bean对象转为map对象
     *
     * @param bean bean对象
     * @return map对象
     */
    public static Map<String, Object> beanToMap(Object bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean == null) {
            return map;
        }
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.forEach((key, value) -> map.put(String.valueOf(key), value));
        return map;
    }

    /**
     * 合并bean
     *
     * @param beans bean对象
     * @return map对象
     */
    public static Map<String, Object> mergeBean(Object... beans) {
        Map<String, Object> map = new HashMap<>();
        for (Object bean : beans) {
            if (bean != null) {
                map.putAll(beanToMap(bean));
            }
        }
        return map;
    }

    /**
     * 导出 JSON 文件
     * @param response
     * @param jsonStr
     * @param fileName
     */
    public static void exportJSON(HttpServletResponse response, String jsonStr, String fileName) {
        BufferedOutputStream bos = null;
        try {
            response.setHeader("Content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
            ServletOutputStream outputStream = response.getOutputStream();
            bos = new BufferedOutputStream(outputStream);
            bos.write(jsonStr.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            throw new DMPException("导出失败");
        } finally {
            try {
                bos.close();
            } catch (Exception e) {
                throw new DMPException("导出失败");
            }
        }
    }
}
